package com.shqcjd.preinstallmobile.ui.activity.remote;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.ess.filepicker.FilePicker;
import com.ess.filepicker.model.EssFile;
import com.ess.filepicker.util.Const;
import com.orhanobut.logger.Logger;
import com.shqcjd.preinstallmobile.R;
import com.shqcjd.preinstallmobile.api.ApiService;
import com.shqcjd.preinstallmobile.app.MyApp;
import com.shqcjd.preinstallmobile.helper.rxjavahelper.RxObserver;
import com.shqcjd.preinstallmobile.helper.rxjavahelper.RxSchedulersHelper;
import com.shqcjd.preinstallmobile.model.ResponseData;
import com.shqcjd.preinstallmobile.model.pojo.FileBean;
import com.shqcjd.preinstallmobile.ui.base.BaseActivity;
import com.shqcjd.preinstallmobile.ui.base.BasePresenter;
import com.shqcjd.preinstallmobile.util.PrefUtils;
import com.shqcjd.preinstallmobile.util.ToastUtils;
import com.tbruyelle.rxpermissions2.RxPermissions;

import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import butterknife.BindView;
import butterknife.OnClick;
import cn.hzw.graffiti.GraffitiActivity;
import cn.hzw.graffiti.GraffitiParams;
import io.agora.AgoraAPI;
import io.agora.AgoraAPIOnlySignal;
import io.agora.IAgoraAPI;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;
import io.agora.rtc.video.VideoEncoderConfiguration;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * 拉取视频流端
 */
public class PullVideoCallActivity extends BaseActivity implements MyApp.OnAgoraEngineInterface {
    private static final int RESULT_GUIDE_FILE_CODE = 112;
    public static final int REQUEST_MEDIA_PROJECTION = 18;
    public static final int REQ_CODE_GRAFFITI = 101;

    @BindView(R.id.remote_video_view_container)
    FrameLayout container;
    @BindView(R.id.cb_call_mute_button)
    CheckBox cbCallMuteButton;
    @BindView(R.id.ll_mute_btn)
    LinearLayout llMuteBtn;
    @BindView(R.id.ll_screenshot_btn)
    LinearLayout llScreenshotBtn;
    @BindView(R.id.ll_file_btn)
    LinearLayout llFileBtn;
    @BindView(R.id.chronometer_layout)
    Chronometer chronometer_layout;
    @BindView(R.id.ll_hang_up_btn)
    LinearLayout llHangUpBtn;
    @BindView(R.id.rl_menu)
    RelativeLayout rlMenu;
    @BindView(R.id.rl_full_screen)
    RelativeLayout rlFullScreen;
    private Context mContext;
    private AgoraAPIOnlySignal mAgoraAPI;
    private RtcEngine mRtcEngine;
    private String channelID;
    private int userID;

    //截图
    private Intent mResultData;
    private int mScreenWidth;
    private int mScreenHeight;
    private ImageReader mImageReader;
    private int mScreenDensity;
    private MediaProjection mMediaProjection;
    private VirtualDisplay mVirtualDisplay;


    private final int TIME = 1000;
    private int timingNum = 10;
    private Handler finishHandler = new Handler();
    private Runnable finishRunnable = new Runnable() {
        @Override
        public void run() {
            if (timingNum == 1) {
                ToastUtils.showShort(mContext, "网络信号不稳定,无法进行远程指导");
                finishHandler.removeCallbacks(finishRunnable);
                new Handler().postDelayed(new Runnable() {
                    public void run() {
                        finish();
                    }
                }, 2000);
            } else {
                timingNum--;
                finishHandler.postDelayed(finishRunnable, TIME);
            }
        }
    };


    @Override
    protected BasePresenter createPresenter() {
        return null;
    }

    @Override
    protected int provideContentViewId() {
        return R.layout.activity_pull_video_call;
    }

    @Override
    public void initView() {
        mContext = this;
        channelID = getIntent().getStringExtra("channelID");
        userID = PrefUtils.getInt(mContext, PrefUtils.USER_ID, -1);

        cbCallMuteButton.setOnCheckedChangeListener(oncheckChangeListerener);

        checkPermissions();


    }

    /**
     * 控制静音
     */
    private CompoundButton.OnCheckedChangeListener oncheckChangeListerener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mRtcEngine.muteLocalAudioStream(isChecked);
        }
    };

    private void checkPermissions() {
        RxPermissions permissions = new RxPermissions(this);
        permissions.setLogging(true);
        permissions.request(Manifest.permission.RECORD_AUDIO,
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        if (aBoolean) {
                            initAgoraEngineAndJoinChannel();
                        } else {
                            ToastUtils.showShort(mContext, "缺少远程指导必要权限");
                            finish();
                        }
                    }
                });
    }

    /**
     * 初始化声网
     */
    private void initAgoraEngineAndJoinChannel() {
        //初始化视频
        initializeAgoraEngine();     // 步骤1
        setupVideoProfile();         // 步骤2
        MyApp.the().setOnAgoraEngineInterface(this);
        //setupLocalVideo();          // 步骤3
        joinChannel();               // 步骤4

        finishHandler.postDelayed(finishRunnable, TIME);

    }

    private void initializeAgoraEngine() {
        mAgoraAPI = MyApp.the().getmAgoraAPI();
        mRtcEngine = MyApp.the().getmRtcEngine();
        if (mRtcEngine != null) {
            mRtcEngine.setLogFile("/sdcard/sdklog.txt");
        }
    }

    private void setupVideoProfile() {
        mRtcEngine.enableVideo();

        VideoEncoderConfiguration.VideoDimensions vd_1280x720 = VideoEncoderConfiguration.VD_1280x720;
        VideoEncoderConfiguration.FRAME_RATE frameRateFps15 = VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15;
        int standardBitrate = VideoEncoderConfiguration.STANDARD_BITRATE;
        VideoEncoderConfiguration.ORIENTATION_MODE orientationModeAdaptive = VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_LANDSCAPE;
        VideoEncoderConfiguration videoEncoderConfiguration = new VideoEncoderConfiguration(vd_1280x720, frameRateFps15, standardBitrate, orientationModeAdaptive);
        mRtcEngine.setVideoEncoderConfiguration(videoEncoderConfiguration);
    }

    private void joinChannel() {
        //开/关本地视频发送。 true：不发送本地视频流
        mRtcEngine.muteLocalVideoStream(true);

        //关闭使用本地摄像头设备 true：开启本地视频采集和渲染（默认）false：关闭使用本地摄像头设备
        mRtcEngine.enableLocalVideo(false);

        //加入信令频道
        mAgoraAPI.channelJoin(channelID);

        int leave = mRtcEngine.leaveChannel();
        int join = mRtcEngine.joinChannel(null, channelID, "Extra Optional Data", userID);// if you do not specify the uid, we will generate the uid for you
        Logger.i("Agora channelID:" + channelID + " 账号:" + userID);
        Logger.i("Agora 加入频道码:" + join + "  离开频道:" + leave+" channelID:"+channelID);
    }


    @Override
    protected void onRestart() {
        super.onRestart();
        rlFullScreen.setVisibility(View.VISIBLE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        addSignalingCallback();
    }

    private void addSignalingCallback() {
        if (mAgoraAPI == null) {
            return;
        }

        mAgoraAPI.callbackSet(new AgoraAPI.CallBack() {
            //发送信息成功
            @Override
            public void onMessageSendSuccess(String messageID) {
                super.onMessageSendSuccess(messageID);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showShort(mContext, "发送成功");
                    }
                });

            }

            //发送消息失败
            @Override
            public void onMessageSendError(String messageID, int ecode) {
                super.onMessageSendError(messageID, ecode);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showShort(mContext, "发送失败");
                    }
                });

            }

            @Override
            public void onLogout(final int i) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (i == IAgoraAPI.ECODE_LOGOUT_E_KICKED) { // 账号其他地方登录---注销
                            ToastUtils.showShort(mContext, "该账户已在别处登录，退出远程指导！");
                            new Handler().postDelayed(new Runnable() {
                                public void run() {
                                    finish();
                                }
                            }, 3000);
                        } else if (i == IAgoraAPI.ECODE_LOGOUT_E_NET) { // 网络问题
                            ToastUtils.showShort(mContext, "网络异常，可能无法发送文件！");
                        }
                    }
                });

            }
        });
    }

    @OnClick({R.id.ll_mute_btn, R.id.ll_screenshot_btn, R.id.ll_file_btn, R.id.ll_hang_up_btn, R.id.rl_full_screen})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.ll_mute_btn://静音
                cbCallMuteButton.setChecked(!cbCallMuteButton.isChecked());
                break;
            case R.id.ll_screenshot_btn://截图
                requestCapturePermission();

                break;
            case R.id.ll_file_btn://选择文件
                FilePicker
                        .from(PullVideoCallActivity.this)
                        .chooseForMimeType()
                        .onlyShowImages()
                        .setMaxCount(1)
                        .setFileTypes("jpg", "doc", "pdf", "txt")
                        .requestCode(RESULT_GUIDE_FILE_CODE)
                        .start();

                break;
            case R.id.ll_hang_up_btn://挂断
                callOutHangup();
                break;
            case R.id.rl_full_screen://显示隐藏菜单
                rlMenu.setVisibility(rlMenu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
                break;
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void requestCapturePermission() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            //5.0 之后才允许使用屏幕截图
            ToastUtils.showShort(this, "当前Android系统版本不支持");
            return;
        }
        MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RESULT_GUIDE_FILE_CODE && resultCode == RESULT_OK) {
            ArrayList<EssFile> essFileList = data.getParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION);
            uploadFile(essFileList.get(0).getAbsolutePath());

        }

        switch (requestCode) {
            case REQUEST_MEDIA_PROJECTION:
                //返回码：0 为取消  -1为确认
                Logger.e("返回码resultCode:" + resultCode);
                if (resultCode == RESULT_OK && data != null) {//确认
                    rlFullScreen.setVisibility(View.GONE);
                    Logger.e("同意了截图");
                    mResultData = data;
                    screenshot();
                } else if (resultCode == RESULT_CANCELED) {//取消
                    rlFullScreen.setVisibility(View.VISIBLE);
                }

                break;
            case REQ_CODE_GRAFFITI:
                if (data == null) {
                    return;
                }
                if (resultCode == GraffitiActivity.RESULT_OK) {
                    String path = data.getStringExtra(GraffitiActivity.KEY_IMAGE_PATH);
                    if (TextUtils.isEmpty(path)) {
                        return;
                    }
                    Logger.e("imgpath:" + path);
                    /*拿到编辑后的图片 上传服务器再推送到眼镜*/
                    uploadFile(path);


                } else if (resultCode == GraffitiActivity.RESULT_ERROR) {
                    Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    /**
     * 上传文件
     *
     * @param path
     */
    private void uploadFile(String path) {
        File file = new File(path);
        ApiService.uploadFile(file)
                .compose(RxSchedulersHelper.io_main())
                .subscribe(new RxObserver<ResponseData<FileBean>>() {
                    @Override
                    public void _onSubscribe(Disposable d) {
                        super._onSubscribe(d);
                        showWaitingDialog("正在上传...");
                    }

                    @Override
                    public void _onNext(ResponseData<FileBean> retData) {
                        if (retData != null && retData.retCode == 10000) {
                            Map<String, String> map = new HashMap<>();
                            map.put("fileId",retData.data.id);
                            map.put("roomId",channelID);
                            sendImage(new JSONObject(map));

                        } else {
                            ToastUtils.showShort(PullVideoCallActivity.this,"上传失败");
                            hideWaitingDialog();
                        }

                    }

                    @Override
                    public void _onError(String errorMessage) {
                        ToastUtils.showShort(PullVideoCallActivity.this,errorMessage);
                        hideWaitingDialog();
                    }

                });
    }

    /**
     * 发送截图
     *
     * @param
     */
    private void sendImage(JSONObject json) {
        ApiService.sendFile(json)
                .compose(RxSchedulersHelper.io_main())
                .subscribe(new Observer<ResponseData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseData retData) {
                        Logger.i("发送截图:"+retData);
                        if (retData.retCode== 10000) {
                            //发送消息信令
                            mAgoraAPI.messageChannelSend(channelID, "", "");
                        } else {
                            ToastUtils.showShort(PullVideoCallActivity.this,"发送失败");
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        hideWaitingDialog();
                    }

                    @Override
                    public void onComplete() {
                        hideWaitingDialog();
                    }
                });
    }

    private void screenshot() {
        createImageReader();
        startScreenShot();
    }

    private void startScreenShot() {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            public void run() {
                //获取当前屏幕内容
                startVirtual();
            }
        }, 100);//5

        handler.postDelayed(new Runnable() {
            public void run() {
                //生成图片保存到本地
                startCapture();

            }
        }, 500);//30
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                clearResource();
            }
        }, 1000);
    }

    private void startVirtual() {
        if (mMediaProjection != null) {
            virtualDisplay();
        } else {
            setUpMediaProjection();
            virtualDisplay();
        }

    }

    /*****释放资源*****/
    private void clearResource() {

        if (mVirtualDisplay == null) {
            return;
        }
        mVirtualDisplay.release();
        mVirtualDisplay = null;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void virtualDisplay() {
        mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mImageReader.getSurface(), null, null);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void setUpMediaProjection() {
        mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private MediaProjectionManager getMediaProjectionManager() {

        return (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    }

    private void startCapture() {

        Image image = mImageReader.acquireLatestImage();

        if (image == null) {
            startScreenShot();
        } else {
//            SaveTask mSaveTask = new SaveTask();
//            AsyncTaskCompat.executeParallel(mSaveTask, image);
            saveCapture(image);

        }
    }

    private void saveCapture(Image image) {
//    Image image = mImageReader.acquireLatestImage();
        int width = image.getWidth();
        int height = image.getHeight();
        final Image.Plane[] planes = image.getPlanes();
        final ByteBuffer buffer = planes[0].getBuffer();
        int pixelStride = planes[0].getPixelStride();
        int rowStride = planes[0].getRowStride();
        int rowPadding = rowStride - pixelStride * width;
        Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
        bitmap.copyPixelsFromBuffer(buffer);
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
        image.close();
        Log.e("startCapture", "bitmap:" + image);


        File file = new File(Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".jpg");
        Logger.e("startCapture: 截图文件file:" + file);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileOutputStream foStream = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, foStream);
            foStream.flush();
            foStream.close();
        } catch (Exception e) {
            Log.i("Show", e.toString());
        }


        String absolutePath = file.getAbsolutePath();

        /*跳转编辑图片 画圈*/
        // 涂鸦参数
        GraffitiParams params = new GraffitiParams();
        // 图片路径
        params.mImagePath = absolutePath;
        // 初始画笔大小
        params.mPaintSize = 20;
        // 启动涂鸦页面
        GraffitiActivity.startActivityForResult(PullVideoCallActivity.this, params, REQ_CODE_GRAFFITI);


    }

    private void createImageReader() {
        WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        mWindowManager.getDefaultDisplay().getMetrics(metrics);
        mScreenDensity = metrics.densityDpi;
        mScreenWidth = metrics.widthPixels;
        mScreenHeight = metrics.heightPixels;

        mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
    }


    /**
     * 设置远程视频
     *
     * @param uid
     */
    // Tutorial Step 5
    private void setupRemoteVideo(int uid) {
        if (container.getChildCount() >= 1) {
            return;
        }
        SurfaceView surfaceView = RtcEngine.CreateRendererView(getBaseContext());

        container.addView(surfaceView);
        //调用 setupRemoteVideo() 方法设置本地看到的远端用户的视频视图
        mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, uid));
        surfaceView.setTag(uid); // 为了标记目标
        //开始计时
        chronometer_layout.setBase(SystemClock.elapsedRealtime());//计时器清零
        chronometer_layout.start();
    }

    private void onRemoteUserOffline(int uid) {
        ToastUtils.showShort(mContext, "对方已挂断,指导结束");
        finish();
    }


    @Override
    public void onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                finishHandler.removeCallbacks(finishRunnable);//移除定时关闭
                setupRemoteVideo(uid);
            }
        });
    }

    @Override
    public void onUserJoined(int uid, int elapsed) {

    }

    @Override
    public void onUserOffline(int uid, int reason) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                onRemoteUserOffline(uid);
            }
        });
    }


    @Override
    public void onUserMuteVideo(int uid, boolean muted) {

    }

    @Override
    public void onJoinChannelSuccess(String channel, int uid, int elapsed) {

    }

    @Override
    public void onError(int err) {

    }


    private void callOutHangup() {
        new MaterialDialog.Builder(mContext)
                .title("远程指导中，是否结束？")
                .positiveText("确认")
                .negativeText("取消")
                .onAny(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        if (which == DialogAction.POSITIVE) {//确认
                            finish();

                        } else if (which == DialogAction.NEGATIVE) {//取消
                            dialog.dismiss();
                        }

                    }
                }).show();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (finishHandler != null) {
            finishHandler.removeCallbacks(finishRunnable);//移除定时关闭
        }
        mAgoraAPI.channelLeave(channelID);
        if (mRtcEngine != null) {
            mRtcEngine.stopPreview();
            mRtcEngine.leaveChannel();//离开频道
        }
//        mRtcEngine = null;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}
